﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace AcademicAudit_JoelShuman
{
    public partial class Form1 : Form
    {
		
				[DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal,
            int size, string filePath);

        public Form1()
        {
            InitializeComponent();
        }

		private void Form1_Load(object sender, EventArgs e)
		{
			//FileStream tempFs = null;
			//StreamReader tempReader = null;
			try
			{
				// Figure out if we are using csv or xml.
				StringBuilder sb = new StringBuilder();
				int res = GetPrivateProfileString("FileType", "FileType", "", sb, sb.Capacity, Path.Combine(Application.StartupPath, "../../ConfigFiles/ingest.cfg"));
				
				if( res != 3 )
				{
					MessageBox.Show("Could not read config file!", "Config File Error");
				}
				if( !String.Equals(sb.ToString(), "XML", StringComparison.CurrentCultureIgnoreCase) && 
					!String.Equals(sb.ToString(), "CSV", StringComparison.CurrentCultureIgnoreCase))
				{
					MessageBox.Show("Invalid FileType config file reading.\n\nRead: " + sb.ToString() +
									"\n\nExpecting XML, xml, CSV, or csv.", "Config File Error");
				}

                // These are setup so I can have access to their dirs for verify student id.
                MainRecords.m_xmlIO = new StudentIOFactory().GetIO("XML");
                MainRecords.m_csvIO = new StudentIOFactory().GetIO("CSV");

				// Get an interface object that knows how to do the desired file IO.
				m_fileIO = new StudentIOFactory().GetIO(sb.ToString());

				// Set the student file directory.
				MainRecords.STUDENTDIR = m_fileIO.GetStudentDirPath();

				// Create a object to hold all the data in memory.
				// Read in all the student records on the disk.
				// Check for null.
				theRecords = m_fileIO.ReadStudentFiles();
				if( theRecords == null)
				{
					MessageBox.Show("Failed reading the student files.", "FileIO Error");
				}

				// If a new student was added via copy and past of files we need to redo the Student ID File.
				StudentIDNumbers.FixIDFile();

				// Populate the combo box.
				PopulateComboBox();

				//theRecords.m_DefaultCourseList = CSVParser.ParseCourseCSV("../../DataFiles/GenericCourseData.csv");
				//// Create an XML Serialized Default Course List.
				//try
				//{
				//	XmlSerializer xx = new XmlSerializer(theRecords.m_DefaultCourseList.GetType());
				//	FileStream tempFss = new FileStream("../../DataFiles/DefaultCourse.xml", FileMode.OpenOrCreate, FileAccess.Write);
				//	StreamWriter tempWriter = new StreamWriter(tempFss);
				//	xx.Serialize(tempWriter, theRecords.m_DefaultCourseList);
				//	tempWriter.Close();
				//	tempFss.Close();
				//}
				//catch (Exception ex)
				//{
				//	Console.WriteLine(ex);
				//}

				// Read in the default course data into memory.  Used when a new student is created.
				//m_fileIO.ReadDefaultCourseFile();
				//XmlSerializer x = new XmlSerializer(typeof(List<Course>));
				//tempFs = new FileStream("../../DataFiles/DefaultCourse.xml", FileMode.Open, FileAccess.Read);
				//tempReader = new StreamReader(tempFs);
				//DefaultCourseList.DEFAULTCOURSELIST = (List<Course>)x.Deserialize(tempReader);
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex);
			}
			finally
			{
				//if (tempReader != null) tempReader.Close();
				//if (tempFs != null) tempFs.Close();
			}
		}

		// Save to disk.
		private void button1_Click(object sender, EventArgs e)
		{
			m_fileIO.SaveToDisk(theRecords);
			MainRecords.UNSAVEDCHANGES = false;
		}

		MainRecords theRecords { get; set; }
		StudentFileIO m_fileIO { get; set; }

		private void buttonAddStudent_Click(object sender, EventArgs e)
		{
			Form2 f = new Form2();
			if( f.ShowDialog() == DialogResult.OK )
			{
				// Read in the default course data into memory.  Used when a new student is created.
				m_fileIO.ReadDefaultCourseFile();

				// Create the student record object.
				StudentRecord tempStudent = new StudentRecord(f.textBoxFirstName.Text, f.textBoxLastName.Text);

				// Call to the interface to create the student file in the correct format.
				if( !m_fileIO.AddStudent(tempStudent) )
				{
					return;
				}
/*				// Write an XML file for the student.
				FileStream tempFs = null;
				StreamWriter tempS = null;
				try
				{
					XmlSerializer x = new XmlSerializer(typeof(StudentRecord));
					tempFs = new FileStream(MainRecords.STUDENTDIR + tempStudent.m_FileName + ".xml", FileMode.OpenOrCreate, FileAccess.Write);
					tempS = new StreamWriter(tempFs);
					x.Serialize(tempS, tempStudent);

					if (!StudentIDNumbers.VerifyID(tempStudent.m_StudentID))
					{
						MessageBox.Show(tempStudent.m_StudentID + " is not a valid Student ID!\n\nUnable to create the student!", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
						// Delete the file.
						File.Delete(MainRecords.STUDENTDIR + tempStudent.m_FileName + ".xml");
						StudentIDNumbers.FixIDFile();
						return;
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex);
				}
				finally
				{
					if (tempS != null) tempS.Close();
					if (tempFs != null) tempFs.Close();
				}
*/
				// Add the Student to the list in memory.
				theRecords.m_AllStudents.Add(tempStudent);
				
				// Add the item to the drop down box.
				comboBox1.Items.Add(tempStudent.m_FileName);

			}
		}
		
		private bool PopulateComboBox()
		{
			foreach (StudentRecord thisRecord in theRecords.m_AllStudents)
			{
				comboBox1.Items.Add(thisRecord.m_FileName);
			}
			return true;
		}
		
			//String selection = comboBox1.SelectedItem.ToString();
			//String [] splitList = selection.Split('_');
			//StudentRecord tempRecord = theRecords.GetStudentByID(splitList[0]);

			//// First Name
			//ListViewItem fName = new ListViewItem("First Name:");
			//fName.SubItems.Add(tempRecord.m_FirstName);
			//// Last Name
			//ListViewItem lName = new ListViewItem("Last Name:");
			//lName.SubItems.Add(tempRecord.m_LastName);
			//// ID
			//ListViewItem id = new ListViewItem("Student ID:");
			//id.SubItems.Add(tempRecord.m_StudentID);
			//// Core Course Completion %
			//ListViewItem coreP = new ListViewItem("Core Course Completion %:");
			//coreP.SubItems.Add(tempRecord.m_CoreCompletionPercentage.ToString());
			//// GenEd Course Completion %
			//ListViewItem genP = new ListViewItem("GenEd Course Completion %:");
			//genP.SubItems.Add(tempRecord.m_GenEdCompletionPercentage.ToString());
			//listViewStudentInfo.Items.AddRange( new ListViewItem[]{fName, lName, id, coreP, genP} );
		private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
		{
			String selection = comboBox1.SelectedItem.ToString();
			String [] splitList = selection.Split('_');

			//UpdateStudentRecord(theRecords.GetStudentByID(splitList[0]));

			// Bind the student data to the grid view.
			BindingSource studentBindingSource = new BindingSource();
			studentBindingSource.DataSource = theRecords.GetStudentByID(splitList[0]);
			dataGridView1.DataSource = studentBindingSource;

			// Bind the student's course data to the grid view.
			BindingSource courseBindingSource = new BindingSource();
			courseBindingSource.DataSource = theRecords.GetStudentByID(splitList[0]).m_CourseList;
			dataGridView2.DataSource = courseBindingSource;
		}

		private void UpdateStudentRecord( StudentRecord theRecord )
		{
			// Lets Verify the ID as well.
			if (!StudentIDNumbers.VerifyID(theRecord.m_StudentID))
			{
				MessageBox.Show(theRecord.m_StudentID + " is not a valid Student ID!\nCould not update the student record.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
            
				//String newValue = dataGridView2.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText.ToString();
            //if (!String.IsNullOrEmpty(dataGridView1.Rows[0].Cells[mFirstNameDataGridViewTextBoxColumn.Index].Value.ToString()))
            if (dataGridView1.RowCount > 0)
            {
                theRecord.m_FirstName = dataGridView1.Rows[0].Cells[mFirstNameDataGridViewTextBoxColumn.Index].Value.ToString();
                theRecord.m_LastName = dataGridView1.Rows[0].Cells[mLastNameDataGridViewTextBoxColumn.Index].Value.ToString();
            }
			theRecord.m_FullName = theRecord.m_FirstName + " " + theRecord.m_LastName;
			theRecord.m_CoreCompletionPercentage = theRecord.CalculateCourseCompletionPercentage(CourseType.CORE);
			theRecord.m_GenEdCompletionPercentage = theRecord.CalculateCourseCompletionPercentage(CourseType.GENED);
            String previousFileName = theRecord.m_FileName;
			theRecord.m_FileName = theRecord.m_StudentID + "_" + theRecord.m_LastName + "_" + theRecord.m_FirstName;
			theRecord.m_GPA = theRecord.CalculateGPA();

            if( !String.Equals(previousFileName, theRecord.m_FileName ) )
            {
                try
                {
                    // Change the file name.
                    File.Move(Path.GetFullPath(MainRecords.STUDENTDIR + previousFileName + ".xml"), Path.GetFullPath(MainRecords.STUDENTDIR + theRecord.m_FileName + ".xml"));
                    
					// Update the combo box for the new name.

					comboBox1.Items.Remove(previousFileName);
					comboBox1.Items.Insert(0,theRecord.m_FileName);
					comboBox1.SelectedItem = theRecord.m_FileName;
                }
                catch( Exception ex)
                {
                    Console.Write(ex);
                    return;
                }
            }
		}

		private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
		{

		}

		private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
            // If the name changes, we need to do some stuff.
			String selection = comboBox1.SelectedItem.ToString();
			String [] splitList = selection.Split('_');
			UpdateStudentRecord(theRecords.GetStudentByID(splitList[0]));
			MainRecords.UNSAVEDCHANGES = true;
		}

		private void dataGridView2_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			// Update the student record.
			String selection = comboBox1.SelectedItem.ToString();
			String[] splitList = selection.Split('_');
			UpdateStudentRecord(theRecords.GetStudentByID(splitList[0]));

			// Need to update dataGridView1 with the new data.
			UpdateValuesInStudentInfoGrid();
			MainRecords.UNSAVEDCHANGES = true;
		}

		private bool ValidateNewInput( String newValue, String columnHeaderText, ref String error)
		{
			String errorMessage = "";
			switch( columnHeaderText )
			{
				case "Course Status":
					{
						if (newValue != "C" && newValue != "I" && newValue != "W")
						{
							errorMessage = newValue + " is not a valid input!\n";
							errorMessage += "Valid options are:\n";
							errorMessage += "\tI for Incomplete\n";
							errorMessage += "\tW for Withdrew\n";
							errorMessage += "\tC for Complete\n";
						}
						break;
					}
				case "Course Grade":
					{
						if( newValue != "UNKNOWN" && newValue != "A"
							&& newValue != "B" && newValue != "C"
							&& newValue != "D" && newValue != "F" )
						{
							errorMessage = newValue + " is not a valid input!\n";
							errorMessage += "Valid options are:\n";
							errorMessage += "\tUNKNOWN\n";
							errorMessage += "\tA\n";
							errorMessage += "\tB\n";
							errorMessage += "\tC\n";
							errorMessage += "\tD\n";
							errorMessage += "\tF\n";
						}
						break;
					}
				case "Course Type":
					{
						if( newValue != "CORE" && newValue != "GENED" && newValue != "ELECTIVE")
						{
							errorMessage = newValue + " is not a valid input!\n";
							errorMessage += "Valid options are:\n";
							errorMessage += "\tCORE\n";
							errorMessage += "\tGENED\n";
							errorMessage += "\tELECTIVE\n";
						}
						break;
					}
				case "Semester":
					{
						if( newValue != "FALL" && newValue != "SPRING"
							&& newValue != "WINTER" && newValue != "SUMMER"
							&& newValue != "NOTSET")
						{
							errorMessage = newValue + "is not a valid input!\n";
							errorMessage += "Valid options are:\n";
							errorMessage += "\tFALL\n";
							errorMessage += "\tSPRING\n";
							errorMessage += "\tWINTER\n";
							errorMessage += "\tSUMMER\n";
							errorMessage += "\tNOTSET\n";
						}
						break;
					}
				default:
					{
						break;
					}
			}
			
			if( !String.IsNullOrEmpty(errorMessage))
			{
				error = errorMessage;
				return false;
			}
			return true;
		}

		private void UpdateValuesInStudentInfoGrid()
		{
			int columnCount = dataGridView1.ColumnCount;
			int rowCount = dataGridView1.RowCount;
			for (int r = 0; r < rowCount; r++)
			{
				for (int c = 0; c < columnCount; c++)
					dataGridView1.UpdateCellValue(c, r);
			}
		}

		// Pad the Course ID with zeros and make the year four digits.
		private void dataGridView2_CellFormatting_1(object sender, DataGridViewCellFormattingEventArgs e)
		{
			if (e.Value != null && (e.ColumnIndex == mCourseIDDataGridViewTextBoxColumn.Index || e.ColumnIndex == myearDataGridViewTextBoxColumn.Index))
			{
				int val = (int)e.Value;
				e.Value = val.ToString("D4"); // apply formating here
				e.FormattingApplied = true;
			}
		}

		private void whereAreTheStudentFilesKeptToolStripMenuItem_Click(object sender, EventArgs e)
		{
			StreamWriter sw = null;
			FileStream fs = null;

			try
			{
				// Create a file showing where the files are kept.
				String fileName = "../../Datafiles/FileLocations.txt";
				fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
				sw = new StreamWriter(fs);

				sw.WriteLine("Student Record Files:\t" + Path.GetFullPath(MainRecords.STUDENTDIR));

                if (sw != null) sw.Close();
                if (fs != null) fs.Close();
                // Open the file.
                Process.Start(Path.GetFullPath(fileName));
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
			}
			finally
			{
				if (sw != null) sw.Close();
				if (fs != null) fs.Close();
			}			
		}

		private void changeLogToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Process.Start(Path.GetFullPath("../../ChangeLog.txt"));
		}

		private void dataGridView2_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{
			// We have illegal data!  Display a helpful message and allow the user to try again!

			if (!String.IsNullOrEmpty(dataGridView2.EditingControl.Text))
			{
				String newValue = dataGridView2.EditingControl.Text;
				//String newValue = dataGridView2.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText.ToString();
				String columnHeaderText = dataGridView2.Columns[e.ColumnIndex].HeaderText;

				String errorMessage = "";
				if (!ValidateNewInput(newValue, columnHeaderText, ref errorMessage))
				{
					MessageBox.Show(errorMessage);
					//return;
					//e.Cancel = true;
				}
				else
					e.Cancel = false;
			}
			else
			{
				MessageBox.Show("Cannot have a blank cell!");
				//return;
				//e.Cancel = true;
			}
			e.Cancel = true;
		}

		private void Form1_FormClosing(object sender, FormClosingEventArgs e)
		{
			if( MainRecords.UNSAVEDCHANGES )
			{
				// Ask if they want to save changes before exiting.
				if (MessageBox.Show("Save before Exit?", "Unsaved Changes!", MessageBoxButtons.YesNo) == DialogResult.Yes)
				{
					m_fileIO.SaveToDisk(theRecords);
					MainRecords.UNSAVEDCHANGES = false;
					MessageBox.Show("Changes Saved!");
				}
			}
		}

		private void label1_Click(object sender, EventArgs e)
		{
			
		}
    }
}
